home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / video / pictetri.src / pictetri / pictetris-src / screen.c < prev    next >
C/C++ Source or Header  |  1996-02-10  |  18KB  |  498 lines

  1. /***************************************************************************\
  2. |*                                       *|
  3. |*  screen.c:    A version of Tetris to run on Linux SVGAlib console.       *|
  4. |*        This module handles all the operations concerning       *|
  5. |*        the Jlib bits.                             *|
  6. |*                                       *|
  7. |*  Authors:    Mike Taylor (mirk@uk.ac.warwick.cs) &               *|
  8. |*        Arturo Espinosa (arturo@nuclecu.unam.mx)           *|
  9. |*  Started:    Fri May 26 12:26:05 BST 1989 (tetris for terminals)       *|
  10. |*            Dic 1, 1995 (pictetris)                       *|
  11. |*                                       *|
  12. \***************************************************************************/
  13.  
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <jlib.h>
  17. #include <sys/types.h>
  18. #include <sys/time.h>
  19. #include <errno.h>
  20.  
  21. #include "screen.h"
  22. #include "pictetris.h"
  23. #include "utils.h"
  24. #include "game.h"
  25. #include "pieces.h"
  26.  
  27. image *pic;                  /* This is a struct of Jlib (palette,data) */
  28. sprite_system *blocks;       /* Another struct... sprite data. */
  29. sprite_system *next_blocks;
  30. buffer_rec *offscreen;       /* The Jlib screen buffer */
  31.  
  32. static FILE *piclist;        /* The pictures list file handle */
  33.  
  34. extern int rand_lines;       /* Number of garbage lines will appear */
  35.  
  36. extern int black_bg;          /* These are some flags which determine the */
  37. extern int next_box;          /* presentation of the screen */
  38.  
  39. extern int piece_no_next;     /* Some parameters which I need for the */
  40. extern int orient_next;       /* next-piece box. */
  41.  
  42. /***************************************************************************\
  43. |*                                       *|
  44. |*  myrefresh() calls the jlib function screen_blit_fs_buffer()    which      *|
  45. |*    copies the buffer into the screen.                   *|
  46. |*                                       *|
  47. \***************************************************************************/
  48.  
  49. void myrefresh () 
  50. {
  51.    screen_blit_fs_buffer(offscreen);
  52. }
  53.  
  54. /***************************************************************************\
  55. |*                                       *|
  56. |*    hoopy_refresh re-draws the screen while playing.               *|
  57. |*                                       *|
  58. \***************************************************************************/
  59.  
  60. void hoopy_refresh ()
  61. {
  62.   setup_screen ();
  63.   draw_board ();
  64.   update_scores ();
  65.   myrefresh ();
  66. }
  67.  
  68. /***************************************************************************\
  69. |*                                       *|
  70. |*    draw_border draws a three dimensional border in the corners        *|
  71. |*    x1,y1 - x2,y2.                               *|
  72. |*                                       *|
  73. \***************************************************************************/
  74.  
  75. void draw_border(int x1,int y1,int x2,int y2)
  76. {
  77.   buff_draw_box(offscreen,x1,y1,x2,y2,1);
  78.   buff_draw_box(offscreen,x1+1,y1+1,x2-1,y2-1,24);
  79.   buff_draw_box(offscreen,x1+2,y1+2,x2-2,y2-2,17);
  80.   buff_draw_box(offscreen,x1+3,y1+3,x2-3,y2-3,19);
  81. }
  82.     
  83. /***************************************************************************\
  84. |*                                       *|
  85. |*  The function print_msg() prints a short message centered on the       *|
  86. |*  floor of the playing area, with a space before and after it.       *|
  87. |*                                       *|
  88. \***************************************************************************/
  89.  
  90. void print_msg (line)
  91.   char *line;
  92. {
  93.   int i;
  94.  
  95.    draw_border(152-COL(strlen(line))/2,183-COL(1),
  96.            168+COL(strlen(line))/2,199);
  97.    buff_draw_rect(offscreen,156-COL(strlen(line))/2,187-COL(1),
  98.            164+COL(strlen(line))/2,196,0);
  99.    buff_draw_string(offscreen,line,160-COL(strlen(line))/2,189-COL(1),1);
  100.   myrefresh ();
  101. }
  102.  
  103. /***************************************************************************\
  104. |*                                       *|
  105. |*  The function clear_area() just puts the pcx on the screen buffer and,  *|
  106. |*  therefore, erases anything there could be on it.               *|
  107. |*                                       *|
  108. \***************************************************************************/
  109.  
  110. void clear_area ()
  111.      {
  112.    buff_blit_img_to(offscreen,0,0,pic,0,0,IMG_WIDTH(pic),IMG_HEIGHT(pic));
  113.      }
  114.  
  115. /***************************************************************************\
  116. |*                                       *|
  117. |*    draw_area puts the pcx on the screen, then draws the borders for   *|
  118. |*    the play ground, the scores box and the next_piece box if          *|
  119. |*    necessary. It also fills the playing area with black if the option *|
  120. |*      is on.                                   *|
  121. |*                                       *|
  122. \***************************************************************************/
  123.  
  124. void draw_area() {
  125.   int i;
  126.    buff_blit_img_to(offscreen,0,0,pic,0,0,IMG_WIDTH(pic),IMG_HEIGHT(pic));
  127.    draw_border(111,5,208,192);
  128.    if (black_bg) buff_draw_rect(offscreen,115,9,204,189,0);
  129.    if (next_box) {
  130.       draw_border(60,5,110,55);
  131.       draw_next_piece_box(piece_no_next,orient_next);
  132.    }
  133.    draw_border(209,5,209+COL(20),9+LINE(5));
  134. }
  135.  
  136. /***************************************************************************\
  137. |*                                       *|
  138. |*    draw_next_piece_box draws the nex... its quite self explanatory.   *|
  139. |*                                       *|
  140. \***************************************************************************/
  141.  
  142. void draw_next_piece_box(piece_no, orient)
  143.   int piece_no;
  144.   int orient;
  145. {
  146.   int i;
  147.    int add=1;       /* this is because most pieces have a (x,-1) upper */
  148.                     /* coordinate... */
  149.    int next_block_no;
  150.    
  151.    if (black_bg) {
  152.       buff_draw_rect(offscreen,64,9,106,52,0); /* draw black bkground */
  153.    } else  {
  154.       for (i=0;i<16;i++)
  155.           buff_rest_sprite(next_blocks,i,offscreen);/* or the image that gets */
  156.    }                                              /* behind the blocks. */
  157.  
  158.       if ((piece_no==1)&&(orient%2==0)) add=0;  /* except the vertical bar */
  159.                                            /* (piece_no 1,orientation 0||2 */
  160.    
  161.    for (i = 0; i < NO_SQUARES; i++) {
  162.       next_block_no=(pieces[piece_no].index[orient][i][0]+add)*4+
  163.                 pieces[piece_no].index[orient][i][1]+1;
  164.                                  /* calculate the number of the sprite */
  165.                               /* (note the use of add to lower the figure) */
  166.       
  167.       sprite_set_an_frame(next_blocks,next_block_no,piece_no+1);
  168.                       /* set the color of the sprite according to the piece */
  169.  
  170.       buff_save_sprite(next_blocks,next_block_no,offscreen);
  171.                             /* this saves the piece of pic under the sprite */
  172.  
  173.       buff_draw_sprite(next_blocks,next_block_no,offscreen);
  174.                                    /* finally draw the sprite on the buffer */
  175.      }
  176. }
  177.  
  178. /***************************************************************************\
  179. |*                                       *|
  180. |*  check_pic_change calls setup_screen when total_time changes by 2500.   *|
  181. |*                                       *|
  182. \***************************************************************************/
  183.  
  184. void check_pic_change()  
  185. {
  186.    int picture_change;
  187.    static int picture_change_last=-1;
  188.    
  189.    picture_change=game_level+rand_lines+(50000-total_time)/2500;
  190.    if (picture_change>picture_change_last) {
  191.       picture_change_last=picture_change;
  192.    } else picture_change++;
  193. }
  194.  
  195. /***************************************************************************\
  196. |*                                       *|
  197. |*    setup_screen calls load_next_pcx                                   *|
  198. |*    and saves the picture under the sprites. Then redraws the buffer.  *|
  199. |*                                       *|
  200. \***************************************************************************/
  201.  
  202. void setup_screen ()
  203. {
  204.    int i,b;
  205.    load_next_pcx();
  206.    clear_area();
  207.    if (black_bg) buff_draw_rect(offscreen,115,9,204,188,0);
  208.    for (i=0;i<200;i++)
  209.      buff_save_sprite(blocks,i,offscreen);
  210.    if (next_box) for (i=0;i<16;i++) 
  211.      buff_save_sprite(next_blocks,i,offscreen);
  212.    draw_area();
  213.    draw_board();
  214. }
  215.  
  216.  
  217. /***************************************************************************\
  218. |*                                       *|
  219. |*    load_next_pcx loads a new picture from the list file           *|
  220. |*                                       *|
  221. \***************************************************************************/
  222.  
  223. void load_next_pcx() {
  224.    char picname[256];
  225.       while (fgets(picname,255,piclist)==NULL) {
  226.      fseek(piclist,0,SEEK_SET);
  227.       }
  228.       picname[strlen(picname)-1]=0;
  229.       image_free(pic);
  230.       pic=image_load_pcx(picname);
  231.       if (pic==NULL) die (LE_USAGE,form("Couldn't load PCX from pictures list file: %s",picname));
  232.       screen_block_set_pal(IMG_PALETTE(pic));
  233. }
  234.  
  235.  
  236. /***************************************************************************\
  237. |*                                       *|
  238. |*  The function setup_curses should be called exactly once, near the       *|
  239. |*  beginning of execution.  It initialises Jlib, and notes that       *|
  240. |*  this has been done, by setting the global variable in_curses.       *|
  241. |*                                       *|
  242. \***************************************************************************/
  243.  
  244. void setup_curses ()
  245. {
  246.    int i;
  247.    int b;
  248.    offscreen=buff_init(SCREEN_WIDTH,SCREEN_HEIGHT);
  249.    if (offscreen==NULL) die(0,"Offscreen buffer could not be allocated.");
  250.    screen_set_video_mode();
  251.    kb_init();
  252.    piclist=fopen(PICLIST_FILE,"r");
  253.    if (piclist==NULL) 
  254.      die(0,form("The file %s could not be opened.",PICLIST_FILE));
  255.    blocks=sprite_init(200,8);
  256.    sprite_load(SPRITE_FILE,blocks);
  257.    for(i=0;i<20;i++)
  258.      for(b=0;b<10;b++) {
  259.     sprite_set_xy(blocks,i*10+b,115+b*9+SPR_MAX_X,9+i*9+SPR_MAX_Y);
  260.     sprite_turn_on(blocks,i*10+b);
  261.     sprite_set_an_frame(blocks,i*10+b,4);
  262.      }
  263.    if (next_box)  {
  264.       next_blocks=sprite_init(16,8);
  265.       sprite_load(SPRITE_FILE,next_blocks);
  266.       for(i=0;i<4;i++)
  267.           for(b=0;b<4;b++) {
  268.        sprite_set_xy(next_blocks,i*4+b,68+b*9+SPR_MAX_X,13+i*9+SPR_MAX_Y);
  269.        sprite_turn_on(next_blocks,i*4+b);
  270.        sprite_set_an_frame(next_blocks,i*4+b,4);
  271.     }
  272.    }
  273.       
  274.    buff_clear(offscreen);
  275.    in_curses = 1;
  276. }
  277.  
  278. /***************************************************************************\
  279. |*                                       *|
  280. |*  The function draw_title loads title.pcx and draws a little message       *|
  281. |*  with the credits.                               *|
  282. |*                                       *|
  283. \***************************************************************************/
  284.  
  285. void draw_title() {
  286.    pic=image_load_pcx(form("%s/title.pcx",TITLE_PATH));
  287.    if (pic==NULL) die (LE_USAGE,form("Couldn't load %s/title.pcx",TITLE_PATH));
  288.    screen_block_set_pal(IMG_PALETTE(pic));
  289.    clear_area();
  290.    draw_border(116,168,204,199);
  291.    buff_draw_rect(offscreen,120,172,200,196,0);
  292.    buff_draw_string(offscreen,"by Arturo Espinosa",124,176,1);
  293.    buff_draw_string(offscreen,"& Mike Taylor.",132,184,1);
  294. }
  295.  
  296. /***************************************************************************\
  297. |*                                       *|
  298. |*  draw_options takes the variables that modify the game difficulty and   *|
  299. |*  draws a square with the information and options available.             *|
  300. |*                                       *|
  301. \***************************************************************************/
  302.  
  303. void draw_options(int bg, int nb, int s, int rl, int tt, int gl) {
  304.    char yn[2][4]= {"No ","Yes"};
  305.    clear_area();
  306.    draw_border(106,120,214,199);
  307.    buff_draw_rect(offscreen,110,124,210,196,0);
  308.    buff_draw_string(offscreen,form("Black BG: %s",yn[bg]),114,128,23);
  309.    buff_draw_string(offscreen,form("Sound: %s",yn[s]),114,128+LINE(1),24);
  310.    buff_draw_string(offscreen,form("Next-piece box: %s",yn[nb]),114,128+LINE(2),17);
  311.    buff_draw_string(offscreen,form("Random lines: %d",rl),114,128+LINE(3),25);
  312.    buff_draw_string(offscreen,form("Level's speed: %d",tt),114,128+LINE(4),18);
  313.    buff_draw_string(offscreen,form("Free falling pieces:%d",gl),114,128+LINE(5),19);
  314.    buff_draw_string(offscreen,"Continue  Keep config",114,128+LINE(6),26);
  315.    buff_draw_string(offscreen,"Quit      View scores",114,128+LINE(7),27);
  316.    buff_draw_string(offscreen,"B",114,128,14);
  317.    buff_draw_string(offscreen,"S",114,128+LINE(1),14);
  318.    buff_draw_string(offscreen,"N",114,128+LINE(2),14);
  319.    buff_draw_string(offscreen,"R",114,128+LINE(3),14);
  320.    buff_draw_string(offscreen,"L",114,128+LINE(4),14);
  321.    buff_draw_string(offscreen,"F",114,128+LINE(5),14);
  322.    buff_draw_string(offscreen,"C         K",114,128+LINE(6),14);
  323.    buff_draw_string(offscreen,"Q         V",114,128+LINE(7),14);
  324.    myrefresh();
  325. }
  326.  
  327. /***************************************************************************\
  328. |*                                       *|
  329. |*  The function update_scores() puts the sepecified values of score,       *|
  330. |*  no_pieces and no_levels on the screen buffer.                             *|
  331. |*                                       *|
  332. \***************************************************************************/
  333.  
  334. void update_scores ()
  335. {
  336.    buff_draw_rect(offscreen,213,9,285,46,0);
  337.    buff_draw_string(offscreen,form("Challenge: %d", game_level+rand_lines+(50000-total_time)/2500),218, 12,1);
  338.    buff_draw_string(offscreen,"Score:",218,12+LINE(1),1);
  339.    buff_draw_string(offscreen,"Pieces:",218,12+LINE(2),1);
  340.    buff_draw_string(offscreen,"Levels:",218,12+LINE(3),1);
  341.    buff_draw_string(offscreen,form ("%d", score),218+COL(7),12+LINE(1),1);
  342.  
  343.    buff_draw_string(offscreen,form ("%d", no_pieces),218+COL(8),12+LINE(2),1);
  344.  
  345.    buff_draw_string(offscreen,form ("%d", no_levels),218+COL(8),12+LINE(3),1);
  346. }
  347.  
  348. /***************************************************************************\
  349. |*                                       *|
  350. |*  The function draw_board() puts the current state of the global array   *|
  351. |*  board[] ontop the buffer (each sprite is a cell on the matrix).        *|
  352. |*                                       *|
  353. \***************************************************************************/
  354.  
  355. void draw_board ()
  356. {
  357.   int i, j;
  358.  
  359.   for (i = 0; i < 20; i++)
  360.    for (j = 0; j < 10; j++) {
  361.       if (board[i+4][j] == PI_EMPTY) {
  362.      buff_rest_sprite(blocks,i*10+j,offscreen);
  363.       }
  364.       sprite_set_an_frame(blocks,i*10+j,board[i+4][j]+1);
  365.       buff_draw_sprite(blocks,i*10+j,offscreen);
  366.    }
  367. }
  368.  
  369. /***************************************************************************\
  370. |*                                       *|
  371. |*  The function draw_piece draws or erases one of the tetris pieces on       *|
  372. |*  the screen in a specified orientation and position.     The form of the   *|
  373. |*  function is:                               *|
  374. |*                                       *|
  375. |*    draw_piece (piece_no, orientation, y, x, flag)               *|
  376. |*                                       *|
  377. |*  All the arrguments are integers.  Flag is either PD_DRAW or           *|
  378. |*  PD_ERASE, specifying the effect of the function.  Piece_no is       *|
  379. |*  between 0 and 6 inclusive, and specifies what sort of piece is       *|
  380. |*  required.  Orientation is between 0 and 3 inclusive, and states       *|
  381. |*  which way up the piece is to be drawn, and y and x express the       *|
  382. |*  position as an index into the 20 by 10 array                       *|
  383. |*  that is the board.                               *|
  384. |*                                       *|
  385. \***************************************************************************/
  386.  
  387. void draw_piece (piece_no, orient, y, x, flag)
  388.   int piece_no;
  389.   int orient;
  390.   int y;
  391.   int x;
  392.   int flag;
  393. {
  394.   int i;
  395.    int block_no;
  396.  
  397.    for (i = 0; i < NO_SQUARES; i++) {
  398.       if (y+pieces[piece_no].index[orient][i][0] >= 0) {
  399.      block_no=(y+pieces[piece_no].index[orient][i][0])*10+
  400.                  x+pieces[piece_no].index[orient][i][1];
  401.      if (flag == PD_ERASE) {
  402.         buff_rest_sprite(blocks,block_no,offscreen);
  403.      } else {
  404.         sprite_set_an_frame(blocks,block_no,piece_no+1);
  405.         buff_save_sprite(blocks,block_no,offscreen);
  406.         buff_draw_sprite(blocks,block_no,offscreen);
  407.      }
  408.       }
  409.    }
  410. }
  411.  
  412. /***************************************************************************\
  413. |*                                       *|
  414. |*  The function place_piece takes the same parameters as draw_piece,       *|
  415. |*  except for the flag, and does not draw the piece, but places it       *|
  416. |*  on the board.  No checking is done to see if it will fit, since       *|
  417. |*  should already have been done by can_place().               *|
  418. |*                                       *|
  419. \***************************************************************************/
  420.  
  421. void place_piece (piece_no, orient, y, x)
  422.   int piece_no;
  423.   int orient;
  424.   int y;
  425.   int x;
  426. {
  427.   int i;
  428.  
  429.   for (i = 0; i < NO_SQUARES; i++)
  430.     board[y+4+pieces[piece_no].index[orient][i][0]]
  431.      [x+pieces[piece_no].index[orient][i][1]] = piece_no;
  432. }
  433.  
  434. /***************************************************************************\
  435. |*                                       *|
  436. |*  The function can_place takes the same parameters as place_piece,       *|
  437. |*  It does not draw the piece, nor place it on the board, but returns       *|
  438. |*  an integer value -- 0 if the piece will not fit on the board, 1 if       *|
  439. |*  it will (with the specified orientation, position, etc.)           *|
  440. |*                                       *|
  441. \***************************************************************************/
  442.  
  443. #define HERE(x) pieces[piece_no].index[orient][i][x]
  444.  
  445. int can_place (piece_no, orient, y, x)
  446.   int piece_no;
  447.   int orient;
  448.   int y;
  449.   int x;
  450. {
  451.   int i;
  452.  
  453.   for (i = 0; i < NO_SQUARES; i++)
  454.     if (((x+HERE(1) >= GAME_WIDTH) ||    /* Off right of screen or */
  455.      (x+HERE(1) < 0)) ||        /* Off left of screen */
  456.     (y+HERE(0) >= GAME_DEPTH) ||    /* Off bottom of screen */
  457.     (board[y+4+HERE(0)][x+HERE(1)] != PI_EMPTY))
  458.                     /* Board position not empty */
  459.       return (0);
  460.   
  461.   return (1);
  462. }
  463.  
  464. /***************************************************************************\
  465. |*                                       *|
  466. |*  flush_keyboard cleans the contents of the buffer.                      *|
  467. |*                                       *|
  468. \***************************************************************************/
  469.  
  470. void flush_keyboard ()
  471. {
  472.    kb_clear();
  473. }
  474.  
  475. /***************************************************************************\
  476. |*                                       *|
  477. |*  get_keyboard_key checks the keyboard's buffer and returns the next       *|
  478. |*  waiting key. Else, it waits until a key is hit.               *|
  479. |*                                       *|
  480. \***************************************************************************/
  481.  
  482. char get_keyboard_key() {
  483.    return kb_get_next_key();
  484. }
  485.  
  486. /***************************************************************************\
  487. |*                                       *|
  488. |*  scan_key returns not zero if the key 'which' (scancode) is             *|
  489. |*  being hit.                                                             *| 
  490. |*                                       *|
  491. \***************************************************************************/
  492.  
  493. char scan_key(int which) {
  494.    return kb_keydown(which);
  495. }
  496.  
  497. /*-------------------------------------------------------------------------*/
  498.